package de.koller.aframe.util.noise.n2D;

import de.koller.aframe.util.math.IFunction2D;
import de.koller.aframe.util.misc.BufferedRandomFloat;
import java.util.LinkedList;

public class ScrollingPerlin2D implements IFunction2D {

	public static boolean PRINT_PROGRESS = false;
	
	private LinkedList<Perlin2DQuadTree> perlins = new LinkedList<>();
	private float maxHeight = 1f;
	public int maxBuffered = 50;
	
	private final BufferedRandomFloat crnd;
	private int steps;
	private float persistence;
	
	public ScrollingPerlin2D( BufferedRandomFloat crnd, int steps, float persistence ) {
		this( crnd, steps, persistence, false );
	}
	
	public ScrollingPerlin2D( BufferedRandomFloat crnd, int steps, float persistence, boolean normalize ) {
		this.crnd = crnd;
		this.steps = steps;
		this.persistence = persistence;
		
		if( normalize )
			this.normalizeMaxBound( Perlin2D.maxHeight( 0, steps, persistence ) );
		
	}

	@Override
	public float getValue( float x, float y ) {
		int vx = (int)Math.floor( x );
		int vy = (int)Math.floor( y );
		float dx = x - vx;
		float dy = y - vy;
		
		return createPerlin( vx, vy ).getValue( dx, dy ) * ( 1f / maxHeight );
	}
	
	public void normalizeMaxBound( float maxHeight ) {
		this.maxHeight = maxHeight;
	}
	
	private synchronized Perlin2DQuadTree createPerlin( int x, int y ) {
		for( Perlin2DQuadTree p : perlins )
			if( p.posY == y && p.posX == x )
				return p;
		
		if( PRINT_PROGRESS )
			System.out.println( "creating perlin: " + x + " / " + y );
		Perlin2DQuadTree cp = Perlin2DQuadTree.create( crnd, x, y, persistence, steps );
		//@todo better buffering
		perlins.addFirst( cp );
		while( perlins.size() > maxBuffered )
			perlins.removeLast();
		
		return cp;
	}
	
}
